﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;

namespace awsomeSyntezator
{
    public class SoundGalery
    {
        private List<Sound> lib;

        public SoundGalery (List<float> freqs)
        {
            lib = new List<Sound>();
            generateGalery(freqs);
        }
        public SoundGalery(string fileName)
        {
			if (lib==null)
			{
				lib = new List<Sound>();
			}
			else
			{
				lib.Clear();
			}
            StreamReader plik;
            plik = File.OpenText(fileName);

            if (plik == null)
            {
                MessageBox.Show(null, "Nie można otwożyć pliku " + fileName, "Błąd", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            string line = plik.ReadLine();

            int start = 0;
            int end = 0;
            int count = 0;

            if (line.Contains("<sounds>"))
            {
                Sound nowy = new Sound();
                while (plik != null)
                {
                    line = plik.ReadLine();

                    if (line.Contains("<sound>"))
                    {
                        nowy = new Sound();
                        continue;
                    }
                    if (line.Contains("</sound>"))
                    {
                        lib.Add(nowy);
                        continue;
                    }
                    if (line.Contains("</sounds>"))
                    {
                        break;
                    }

                    if (line.Contains("<oscilator>"))
                    {
                        int tempType = 0;
                        float tempFrequency = 0.0f;
                    	int tempStrengh = 1;
                        for (int i = 0; i < 2; i++)
                        {
                            line = plik.ReadLine();

                            if (line.Contains("<type>"))
                            {
                                start = line.IndexOf(">") + 1;
                                end = line.IndexOf("<", start);
                                count = end - start;
                                tempType = Convert.ToInt32(line.Substring(start, count));
                                continue;
                            }
                            if (line.Contains("<frequency>"))
                            {
                                start = line.IndexOf(">") + 1;
                                end = line.IndexOf("<", start);
                                count = end - start;
                                tempFrequency = (float)Convert.ToDouble(line.Substring(start, count));
                                continue;
                            }
							if (line.Contains("<strengh>"))
							{
								start = line.IndexOf(">") + 1;
								end = line.IndexOf("<", start);
								count = end - start;
								tempStrengh = Convert.ToInt16(line.Substring(start, count));
								continue;
							}
                        }
                        if (tempFrequency>0)
							nowy.pipe.addOscilator(tempFrequency, tempType, tempStrengh);
                        continue;
                    }
                    if (line.Contains("<envelope>"))
                    {
                        int tempType = 0;
                        int tempStrengh = 0;
                    	int tempFrequency = 1;

                        for (int i = 0; i < 2; i++)
                        {
                            line = plik.ReadLine();

                            if (line.Contains("<type>"))
                            {
                                start = line.IndexOf(">") + 1;
                                end = line.IndexOf("<", start);
                                count = end - start;
                                tempType = Convert.ToInt32(line.Substring(start, count));
                                continue;
                            }
                            if (line.Contains("<strengh>"))
                            {
                                start = line.IndexOf(">") + 1;
                                end = line.IndexOf("<", start);
                                count = end - start;
                                tempStrengh = Convert.ToInt32(line.Substring(start, count));
                                continue;
                            }
							if (line.Contains("<frequency>"))
							{
								start = line.IndexOf(">") + 1;
								end = line.IndexOf("<", start);
								count = end - start;
								tempFrequency = Convert.ToInt16(line.Substring(start, count));
								continue;
							}
                        }
                        if (tempStrengh > 0)
							nowy.pipe.addEnvelope(tempStrengh, tempType, tempFrequency);
                        continue;
                    }
                    if (line.Contains("<effect>"))
                    {
                        int tempType = 0;
                        float tempCutOffFrequency = 0.0f;
                    	double tempResonance = 0.0;

                        for (int i = 0; i < 2; i++)
                        {
                            line = plik.ReadLine();

                            if (line.Contains("<type>"))
                            {
                                start = line.IndexOf(">") + 1;
                                end = line.IndexOf("<", start);
                                count = end - start;
                                tempType = Convert.ToInt32(line.Substring(start, count));
                                continue;
                            }
                            if (line.Contains("<cutOffFrequency>"))
                            {
                                start = line.IndexOf(">") + 1;
                                end = line.IndexOf("<", start);
                                count = end - start;
								tempCutOffFrequency = (float)Convert.ToDouble(line.Substring(start, count));
                                continue;
                            }
							if (line.Contains("<resonance>"))
							{
								start = line.IndexOf(">") + 1;
								end = line.IndexOf("<", start);
								count = end - start;
								tempResonance = Convert.ToDouble(line.Substring(start, count));
								continue;
							}
                        }
						if (tempCutOffFrequency > 0)
							nowy.pipe.addEffect(tempCutOffFrequency, tempResonance, tempType);
                        continue;
                    }
                }
            }
            updateGalery();
        }

        public void playSound (int i)
        {
			if(lib.Count == 0)
				return;
			if (i >= lib.Count)
			{
				i = 0;
			}
			if (Options.live)
				lib[i].playOnLive();
			else
				lib[i].play();
        }

        public void generateGalery(List<float> freqs)
        {
			lib.Clear();
            for (int i =0; i<freqs.Count; i++)
            {
                lib.Add(new Sound());
				lib[i].pipe.generatePipe(freqs[i]);
                lib[i].createSound();
            }
        }

        public void updateGalery()
        {
            foreach (Sound t in lib)
            {
                t.createSound();
            }
        }

    	public short[] getSoundSamples(int soundNr)
    	{
    		short[] samples = new short[Options.samples];
			
			IntPtr ptr1 = new IntPtr();
			IntPtr ptr2 = new IntPtr();
			uint len1 = 0;
			uint len2 = 0;
			uint first = 0;

			lib[soundNr].sound.@lock(first, (uint)Options.samples, ref ptr1, ref ptr2, ref len1, ref len2);

			unsafe
			{
				Int16* dataPtr = (Int16*)ptr1; //wskaźnik do pojedynczych próbek

				for (int i = 0; i < Options.samples; i++)
				{
					samples[i] = dataPtr[i];
				}
			}
			lib[soundNr].sound.unlock(ptr1, ptr2, len1, len2);


    		return samples;
    	}
    }
}
